using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Resources;
using System.Reflection;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Windows.Forms;
using Optimus;

//Copyright 2007 Scott Hanselman
// http://www.hanselman.com/blog
//  with help from Matt Davis

namespace OptimusNothing
{
    [ComVisible(true)]
    [ProgId("Optimus.Nothing")]
    public class Foo : IOptimusPlugin
    {
        private Dictionary<Info, int> _infoBag;
        private Dictionary<string, string> _propBag;
        private Dictionary<string, string> _sharedPropBag;
        private Icon _icon; // keep a managed ref to the Icon to prevent premature GC

        public Foo()
        {
            _infoBag = new Dictionary<Info, int>();
            _infoBag.Add(Info.KEY, retStr("optimus.nothing"));
            _infoBag.Add(Info.NAME, retStr("Optimus Nothing"));
            _infoBag.Add(Info.DESC, retStr("Example managed plugin for the Optimus Mini Three keyboard. Thanks to Matt Davis for the help."));
            _infoBag.Add(Info.AUTHOR, retStr("Scott Hanselman"));
            _infoBag.Add(Info.EMAIL, retStr("scott at hanselman.com"));
            _infoBag.Add(Info.HOMEPAGE, retStr("http://www.hanselman.com"));
            
            _icon = new Icon(Assembly.GetExecutingAssembly().GetManifestResourceStream("OptimusNothing.Nothing.ico"));

            // this handle is immediately eligible for GC...
            _infoBag.Add(Info.ICON32, _icon.Handle.ToInt32());
            _infoBag.Add(Info.FUNCTIONS, 1);
            _infoBag.Add(Info.HAS_PROPERTIES, 1);
            _infoBag.Add(Info.HAS_SHARED_PROPERTIES, 1);

            _infoBag.Add(Info.DELAY, 350); // wonder how low you can go on the real hardware?
            
            _propBag = new Dictionary<string, string>();
            _propBag.Add("PropName1", "PropValue1");
            _propBag.Add("PropName2", "PropValue2");
            
            _sharedPropBag = new Dictionary<string, string>();
            _sharedPropBag.Add("SharedProp1", "Blee");
            _sharedPropBag.Add("SharedProp2", "Zazazaza");

        }
        
        public int GetInfo(Info index)
        {
            Debug.WriteLine("GetInfo wants " + index.ToString());
    
            int value;

            if(_infoBag.TryGetValue(index, out value))
                return value;

            return 0;
        }

        public void OnKeyDown()
        {
            Debug.WriteLine("Button down");
            return;
        }

        private int _paintCount;
        public bool Paint(IntPtr HDC)
        {
            _paintCount++;
            using (Graphics g = Graphics.FromHdc(HDC))
            {
                Brush b = ((_paintCount % 2 == 0) ? Brushes.Blue : Brushes.Red);
                g.FillRectangle(b, new Rectangle(0, 0, 96, 96));
            }
            if (_paintCount > 100) _paintCount = 0;
            return true;
        }

        private static int retStr(string managedString)
        {
            Debug.WriteLine("Returning \"" + managedString + "\" to unmanaged code.");
            return Marshal.StringToHGlobalAnsi(managedString).ToInt32();
        }

        public bool GetProperty(int rawIndex, out string name, out string value)
        {
            int bagIndex = -1;
            name = null;
            value = null;

            Dictionary<string, string> bag = null;

            // select which bag to pull from
            if((rawIndex >= Utilities.PLUGIN_PROPERTIES) && (rawIndex < Utilities.PLUGIN_SHARED_PROPERTIES))
            {
                bag = _propBag;
                bagIndex = rawIndex - Utilities.PLUGIN_PROPERTIES;
                Debug.WriteLine("GetProperty (PLUGIN_PROPERTIES) : " + bagIndex);
            }
            else if(rawIndex >= Utilities.PLUGIN_SHARED_PROPERTIES)
            {
                bag = _sharedPropBag;
                bagIndex = rawIndex - Utilities.PLUGIN_SHARED_PROPERTIES;
                Debug.WriteLine("GetProperty (PLUGIN_SHARED_PROPERTIES) : " + bagIndex);
            }
            else
                return false; // unexpected propIndex < 256, just bail

            if(bagIndex >= bag.Count)
                return false; // signal that we're out of items
                
            int curIndex = 0;

            // sucky, but it works
            foreach (KeyValuePair<string, string> kvp in bag)
            {
                if (bagIndex == curIndex++)
                {
                    name = kvp.Key;
                    value = kvp.Value;
                    return true;
                }
            }

            return false; // catchall
        }

        public bool OnEvent(OptimusEvent evt)
        {
            Debug.WriteLine("Event " + evt + " fired");
            return true;
        }

        public bool SetProperty(string name, string value)
        {
            return true;
        }

        public bool ShowProperties(IntPtr hwnd)
        {
            PropertiesForm pf = new PropertiesForm();
            pf.ShowDialog(new Win32WindowWrapper(hwnd));
            return true;
        }

    }

    

}
